查看原文
其他

网鼎杯2020 伪虚拟机逆向 wp

菜鸟m号 看雪学院 2021-03-07
本文为看雪论坛优秀文章
看雪论坛作者ID:菜鸟m号


解题速度太慢了,导致下午开始肝ta的时候,分数不过200了。

终端程序,无壳,gcc编译:

复制完vmtable之后进入调度算法:

int __cdecl main(int argc, const char **argv, const char **envp){ int table2; // [esp+18h] [ebp-1D4h] __main(); qmemcpy(&table2, byte_403040, 0x1C8u); vm_operad(&table2, 'r'); puts("good,The answer format is:flag {}"); return 0;}

说是伪虚拟机,因为这个明显是仿照vm的意思自己完成switch小demo,没有寄存器也没啥调度算法:

int __cdecl vm_operad(int *table, int a2){ int result; // eax char input[100]; // [esp+13h] [ebp-E5h] char v4[100]; // [esp+77h] [ebp-81h] char v5; // [esp+DBh] [ebp-1Dh] int v6; // [esp+DCh] [ebp-1Ch] int v7; // [esp+E0h] [ebp-18h] int v8; // [esp+E4h] [ebp-14h] int v9; // [esp+E8h] [ebp-10h] int v10; // [esp+ECh] [ebp-Ch] v10 = 0; v9 = 0; v8 = 0; v7 = 0; v6 = 0; while ( 1 ) { result = v10; if ( v10 >= a2 ) return result; switch ( table[v10] ) { case 1: v4[v7] = v5; ++v10; ++v7; ++v9; break; case 2: v5 = table[v10 + 1] + input[v9]; v10 += 2; break; case 3: v5 = input[v9] - LOBYTE(table[v10 + 1]); v10 += 2; break; case 4: v5 = table[v10 + 1] ^ input[v9]; v10 += 2; break; case 5: v5 = table[v10 + 1] * input[v9]; v10 += 2; break; case 6: ++v10; break; case 7: if ( v4[v8] != table[v10 + 1] ) // 最终比较 { printf("what a shame..."); exit(0); } ++v8; v10 += 2; break; case 8: input[v6] = v5; // 把之前的处理值放回到input中 ++v10; ++v6; break; case 10: read(input); // 先执行read函数 ++v10; break; case 11: v5 = input[v9] - 1; ++v10; break; case 12: v5 = input[v9] + 1; ++v10; break; default: continue; } }}

table:

int table[] = { 0x0A, 4, 0x10, 3, 5, 1, 4, 0x20, 8, 5, 3, 1, 3, 2, 0x8, 0x0B, 1, 0x0C, 8, 4, 4, 1, 5, 3, 8, 3, 0x21, 1, 0x0B, 8, 0x0B, 1, 4, 9, 8, 3, 0x20, 1, 2, 0x51, 8, 4, 0x24, 1, 0x0C, 8, 0x0B, 1, 5, 2, 8, 2, 0x25, 1, 2, 0x36, 8, 4, 0x41, 1, 2, 0x20, 8, 5, 1, 1, 5, 3, 8, 2, 0x25, 1, 4, 9, 8, 3,

0x20, 1, 2, 0x41,

8, 0x0C, 1, 7,

0x22, 7, 0x3F, 7,

0x34, 7, 0x32, 7,

0x72, 7, 0x33, 7,

0x18, 7, 0xA7, 0xFF, 0xFF, 0xFF, 7,

0x31, 7, 0xF1, 0xFF, 0xFF,

0xFF, 7, 0x28, 7, 0x84, 0xFF,

0xFF, 0xFF, 7, 0xC1, 0xFF, 0xFF, 0xFF, 7,

0x1E, 7, 0x7A };


第一个关键地方是case 7下的比较,table[10+1]明显每次比较的时候都是一个定值,动态时候记录下来:

断在4016E2处,动态调试记录每次eax值:

0x22,0x3F,0x34,0x32,0x72,0x33,0x18,0xFA7,0x31,0xF1,0x28,0xF84,0xC1,0x1E,0x7A

比较的关键是:


而v4是case 1的时候保存。

所以分析一下指令:
table[1], 的read函数就是接收用户输入,然后4, 0x10, 3, 5, 1, 这样类似的一套就是一个handler,并且计算值等于最后比较的数组。

所有的handler:

10h ^ input[1]-5 = 22h(20h ^input[2])*3=3Fhinput[3]-2-1=34h(input[4]+1 )^4 =32 hinput[5]*3-21h=72hinput[6]-1-1=33h9^input[7]-20=18(51h +input[8])^24h=FA7input[9]+1-1=31h2*input[10]+25h=F1h(36h+input[11]) ^41h =28h(20h + input[12])*1=F84h3*input[13]+25h=C1h9^input[14]-20h=1E h41h + input[15] +1 =7A h

757515121f3d478

没办法,师傅们都是秒题,我只能一个一个还原。



-End -





看雪ID:菜鸟m号

https://bbs.pediy.com/user-856851.htm 

*这里由看雪论坛 菜鸟m号 原创,转载请注明来自看雪社区。

推荐文章++++

*   D-Link DIR-645路由器栈溢出漏洞分析

*   TP-Link Archer路由器LAN RCE

*   记一次基于Soket通信的app的分析

*   开源一个Linux进程内存内核管理模块源码

*   由一道CTF对10种反调试的探究


好书推荐






公众号:ikanxue
官方微博:看雪安全
商务合作:wsc@kanxue.com



“阅读原文” 一起来充电吧!

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存